package com.epalmpay.service.trade.impl;

import com.epalmpay.dto.bonus.BonusSendLogListOutDTO;
import com.epalmpay.dto.bonus.BonusSendLogOutDTO;
import com.epalmpay.dto.datareport.TradeCheckedInDTO;
import com.epalmpay.dto.system.TradeOfflineBaseOutDTO;
import com.epalmpay.dto.trade.DeviceOfflineRecordInDTO;
import com.epalmpay.dto.trade.DeviceOfflineRecordListOutDTO;
import com.epalmpay.dto.trade.TradeCouponInfoDTO;
import com.epalmpay.dto.trade.XYJTradeOutDTO;
import com.epalmpay.entity.*;
import com.epalmpay.enumdef.BizEnum;
import com.epalmpay.exception.ApplicationException;
import com.epalmpay.mapper.*;
import com.epalmpay.payplat.IPayAPI;
import com.epalmpay.payplat.TkRefund;
import com.epalmpay.payplat.result.RefundResult;
import com.epalmpay.service.app.IAppNoticeService;
import com.epalmpay.service.trade.IDevOfflineRecordService;
import com.epalmpay.service.weixin.IWalletService;
import com.epalmpay.status.Rescode;
import com.epalmpay.util.DateUtil;
import com.epalmpay.util.Tools;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * Created by wucongpeng on 2017/5/4.
 */

@Service("devOfflineService")
public class DevOfflineRecordServiceImpl implements IDevOfflineRecordService{

    @Resource
    private TradeOfflineMapper tradeOfflineMapper;

    @Autowired
    private MemberMapper memberMapper;

    @Resource
	private IWalletService walletService;
    @Resource
    private IAppNoticeService appNoticeService;

    @Resource
    private ShopMapper shopMapper;
    
    @Resource
	private StatisMemberMapper statisMemberMapper;

    @Resource
    private MemberGradeMapper memberGradeMapper;

    @Resource
    private MachineWasherMapper machineWasherMapper;


    /**交易记录列表分页
     * @return
     * @throws Exception
     */
    @Override
    public List<TradeOffline> listOfflineRecords(DeviceOfflineRecordInDTO offlineRecordInDTO, Page page)throws Exception{

        TradeOffline tradeOffline = new TradeOffline();
        tradeOffline.setPage(page);
        tradeOffline.setGroupId(offlineRecordInDTO.getGroupId());
        tradeOffline.setReceiverId(offlineRecordInDTO.getReceiverId());
        tradeOffline.setReceiverName(offlineRecordInDTO.getReceiverName());
        tradeOffline.setTransactionStatus(offlineRecordInDTO.getTransactionStatus());
        tradeOffline.setTransactionType(offlineRecordInDTO.getTransactionType());
        tradeOffline.setPayType(offlineRecordInDTO.getPayType());
        tradeOffline.setOrderId(offlineRecordInDTO.getOrderId());
        tradeOffline.setAgentId(offlineRecordInDTO.getAgentId());
        tradeOffline.setShopId(offlineRecordInDTO.getShopId());
        if (!Tools.isEmpty(offlineRecordInDTO.getJoinStart())) {
            tradeOffline.setJoinStart(DateUtil.fomatDate(offlineRecordInDTO.getJoinStart()));
        }
        if (!Tools.isEmpty(offlineRecordInDTO.getJoinEnd())) {
            tradeOffline.setJoinEnd(DateUtil.fomatDate(offlineRecordInDTO.getJoinEnd()));
        }
        if(offlineRecordInDTO.getSubType()!=null){
        	tradeOffline.setSubType(offlineRecordInDTO.getSubType()); 
        }
        if(offlineRecordInDTO.getPaymentScene()!=null){
        	tradeOffline.setPaymentScene(offlineRecordInDTO.getPaymentScene());
        }

        List<TradeOffline> tradeOfflineList = tradeOfflineMapper.OfflineRecordlistPage(tradeOffline);

        return tradeOfflineList;
    }

    
    public List<TradeOffline> listCheckOfflineRecords(TradeCheckedInDTO offlineRecordInDTO, Page page)throws ApplicationException
    {
    	 TradeOffline tradeOffline = new TradeOffline();
         tradeOffline.setPage(page);
         tradeOffline.setGroupId(offlineRecordInDTO.getGroupId());
//         tradeOffline.setReceiverId(offlineRecordInDTO.getReceiverId());
         tradeOffline.setReceiverName(offlineRecordInDTO.getReceiverName());
         tradeOffline.setTransactionType(offlineRecordInDTO.getTransactionType());
         tradeOffline.setPayType(offlineRecordInDTO.getPayType());
         tradeOffline.setOrderId(offlineRecordInDTO.getOrderId());  
         if(offlineRecordInDTO.getCheckStatus()!=null){
        	 tradeOffline.setCheckStatus(offlineRecordInDTO.getCheckStatus().intValue());
         }
         
         if (!Tools.isEmpty(offlineRecordInDTO.getJoinStart())) {
             tradeOffline.setJoinStart(DateUtil.fomatDate(offlineRecordInDTO.getJoinStart()));
         }
         if (!Tools.isEmpty(offlineRecordInDTO.getJoinEnd())) {
             tradeOffline.setJoinEnd(DateUtil.getDateNext(offlineRecordInDTO.getJoinEnd(), 1));
         }
         if(offlineRecordInDTO.getSubType()!=null){
         	tradeOffline.setSubType(offlineRecordInDTO.getSubType()); 
         }

         List<TradeOffline> tradeOfflineList = tradeOfflineMapper.OfflineRecordChecklistPage(tradeOffline);

         return tradeOfflineList;
    }

    @Override
    public TradeOffline offlinefindByOrderId(TradeOffline offline) throws Exception {
        TradeOffline tradeOffline = new TradeOffline();
        Map<String, Object> result = tradeOfflineMapper.selectOfflineByOrderId(offline.getOrderId());
        if (result != null){
            tradeOffline.setOrderId((String) result.get("order_id"));

            tradeOffline.setRealAmount(new Integer(String.valueOf((Long) result.get("real_amount"))));
            if (result.get("pay_type") != null) {
                tradeOffline.setPayType(Byte.parseByte(String.valueOf((Integer) result.get("pay_type"))));
            }
            if(result.get("transaction_status") != null) {
                tradeOffline.setTransactionStatus(Byte.parseByte(String.valueOf((Integer) result.get("transaction_status"))));
            }
            tradeOffline.setGmtModified((Date) result.get("gmt_modified"));
            tradeOffline.setMemo((String) result.get("memo"));
        }
        return tradeOffline;
    }

    @Override
    public String offlineOldOrderIdfindByOrderId(Long id) throws Exception {
        return tradeOfflineMapper.selectOldOrderId(id);
    }

    /**通过id获取数据
     * @return
     * @throws Exception
     */
    @Override
    public TradeOffline offlinefindById(TradeOffline offline)throws Exception{

        //查询交易表信息
        TradeOffline tradeOffline = tradeOfflineMapper.selectOfflineById(offline.getId());

        //查询会员信息和会员等级
        if (offline.getMemberId() != null){
            Map<String, Object> map1 = tradeOfflineMapper.selectMemberInfoById(offline.getMemberId());
            if (map1 != null) {
                tradeOffline.setMemberId((Long) map1.get("memberId"));
                tradeOffline.setCardNo((String) map1.get("cardNo"));
                tradeOffline.setMemberName((String) map1.get("memberName"));
                tradeOffline.setGradeName((String) map1.get("gradeName"));
                tradeOffline.setFromName((String) map1.get("fromName"));
                if (!tradeOffline.getPayerId().equals(offline.getMemberId())){
                    tradeOffline.setReceiverName(tradeOffline.getPayerName());
                }
            }
        }else{
            Map<String, Object> map2 = tradeOfflineMapper.selectMemberInfoById(tradeOffline.getPayerId());
            if (map2 != null) {
                tradeOffline.setMemberId((Long) map2.get("memberId"));
                tradeOffline.setCardNo((String) map2.get("cardNo"));
                tradeOffline.setMemberName((String) map2.get("memberName"));
                tradeOffline.setGradeName((String) map2.get("gradeName"));
                tradeOffline.setFromName((String) map2.get("fromName"));
            }
        }


        //查询消费返现
        /*TradeOffline tradeOffline1 = tradeOfflineMapper.selectOfflineBackAmtById(offline.getId());
        if (tradeOffline1 != null){
            tradeOffline.setBackAmount(tradeOffline1.getOrderAmount());
        }*/
        TradeOffline tradeOffline1 =null;
        if (offline.getMemberId() != null) {
            tradeOffline1 = tradeOfflineMapper.getTradeDataByRelatedTradeOfflineId(offline.getId(), offline.getMemberId().toString());
//        TradeOffline tradeOffline1 = tradeOfflineMapper.selectOfflineBackAmtById(offline.getId());
        }else if(tradeOffline.getPayerId() !=null){
            tradeOffline1 = tradeOfflineMapper.getTradeDataByRelatedTradeOfflineId(offline.getId(), tradeOffline.getPayerId().toString());
        }
        if (tradeOffline1 != null){
            tradeOffline.setBackAmount(tradeOffline1.getOrderAmount());
        }

        //查询优惠券
        int count = tradeOfflineMapper.selectOfflineCouponCountById(offline.getId());
        if (count>0){
            tradeOffline.setCouponCount(count);
            List<Map<String, Object>> coupons = tradeOfflineMapper.selectOfflineCouponsById(offline.getId());
            if (coupons != null){
                List<TradeCouponInfoDTO> couponInfos = new ArrayList<>();
                for (int i = 0; i <coupons.size(); i++) {
                    TradeCouponInfoDTO couponInfoDTO = new TradeCouponInfoDTO();
                    couponInfoDTO.setCouponName((String) coupons.get(i).get("couponName"));
                    couponInfoDTO.setCouponValue((Integer) coupons.get(i).get("couponValue"));
                    couponInfoDTO.setCouponType((Integer) coupons.get(i).get("couponType"));
                    couponInfos.add(couponInfoDTO);
                }
                tradeOffline.setCouponInfo(couponInfos);

            }
        }

        return tradeOffline;
    }

	@Override
	public TradeOfflineBaseOutDTO updateTkReimburse(DeviceOfflineRecordInDTO deviceOfflineRecordInDTO) throws ApplicationException {
		TradeOfflineBaseOutDTO baseOutDTO=new TradeOfflineBaseOutDTO();
		
		TradeOffline tradeOffline=tradeOfflineMapper.selectByPrimaryKey(deviceOfflineRecordInDTO.getId());
		if(tradeOffline==null||!tradeOffline.getTransactionStatus().equals((byte) BizEnum.TransactionStatus.Success.getType())){
			baseOutDTO.setErrorCode(Rescode.FAIL, "该订单未支付成功或不存在");
			return baseOutDTO;
		}
		tradeOffline.setDetail("台卡退款");
		tradeOffline.setTransactionStatus((byte) BizEnum.TransactionStatus.ISRefund.getType());
		
		
		//判断支付方式  钱包退款 直接返回到钱包
		if(tradeOffline.getPayType().equals((byte) BizEnum.PaymentType.Wallet.getType())){ 
			 
			 Member member =memberMapper.queryGroup(tradeOffline.getPayerId());
			 if(member!=null){
				 //这里暂时把退款金额 全部退款至不可提现金额
		            walletService.updateUserLockedAmount(member.getVirtualCard(), member.getPayGroupCode(), member.getUserId(), tradeOffline.getRealAmount()+"", "0", 0,tradeOffline.getOrderId());
			 }else{
				 baseOutDTO.setErrorCode(Rescode.FAIL, "退款失败");
				 return baseOutDTO;
			 }
			
			
		}else if(tradeOffline.getPayType().equals((byte) BizEnum.PaymentType.WebChat.getType())){
			TkRefund tkRefund=TkRefund.initialize("WECHAT", tradeOffline.getMerchantNo(), tradeOffline.getOrderId(), tradeOffline.getRealAmount()+"",
					tradeOffline.getRealAmount()+"", tradeOffline.getTerminalNo());
			
			RefundResult payResult=IPayAPI.finishTkRefund(tkRefund);
			
			if (!payResult.getResult_code().equals("000000")) {
				throw new ApplicationException(Rescode.FAIL, "调用失败" + payResult.getResult_msg());
			}
			tradeOffline.setTransOrderNo(payResult.getRefund_order_no());
			
		}else if(tradeOffline.getPayType().equals((byte) BizEnum.PaymentType.AliPay.getType())){
			//支付宝 微信台卡退款
			
			TkRefund tkRefund=TkRefund.initialize("ALIPAY", tradeOffline.getMerchantNo(), tradeOffline.getOrderId(), tradeOffline.getRealAmount()+"",
					tradeOffline.getRealAmount()+"", tradeOffline.getTerminalNo());
			RefundResult payResult=IPayAPI.finishTkRefund(tkRefund);
			
			if (!payResult.getResult_code().equals("000000")) {
				throw new ApplicationException(Rescode.FAIL, "支付宝调用失败" + payResult.getResult_msg());
			}
			tradeOffline.setTransOrderNo(payResult.getRefund_order_no());
		}
	//	tradeOfflineMapper.updateByPrimaryKeySelective(tradeOffline);
		
		
		
		 //退款成功 更新会员的消费总额跟消费次数
		memberMapper.updateMemberUpdateAmount(tradeOffline.getPayerId(),tradeOffline.getRealAmount());
		statisMemberMapper.updateMemberCostomerInfo(tradeOffline.getPayerId(),tradeOffline.getRealAmount());
		
        //退款成功后判断是否需要降低会员的等级
        //如果有付款者ID,就去查询付款者是否是会员
        if(tradeOffline.getPayerId()!=null){
            Member memberupdateTemp= memberMapper.selectByPrimaryKey(tradeOffline.getPayerId());
            //是会员
            if(memberupdateTemp!=null){
                //查询到会员等级降级的等级ID
                MemberGrade memberGrade = memberGradeMapper.selectDownGradeIdByAmount(memberupdateTemp.getGroupId(), memberupdateTemp.getUpdateAmount());
                //如果该会员当前的等级ID不等于其消费总额该拥有的等级，则判断为需要降级，进行降级操作
                if(memberGrade != null && (!memberupdateTemp.getGradeId().equals(memberGrade.getId()))){
                    Member memberUpdate = new Member();

                    //如果查询到的会员晋级金额为0，就默认将该会员修改为关注会员
                    if(memberGrade.getUpdateAmount().equals(0)){
                        MemberGrade memberGradeTemp = new MemberGrade();
                        memberGradeTemp.setMerchantId(memberupdateTemp.getGroupId());
                        memberGradeTemp.setName(BizEnum.MemberGradeDefault.attention.getName());
                        MemberGrade getMemberGradeId=memberGradeMapper.selectMemberGradeByGroupIdAndGradeName(memberGradeTemp);
                        memberUpdate.setGradeId(getMemberGradeId.getId());
                    }else{
                        memberUpdate.setGradeId(memberGrade.getId());
                    }
                    memberUpdate.setId(memberupdateTemp.getId());
                    memberUpdate.setUpdateTime(new Date());
                    memberMapper.updateByPrimaryKeySelective(memberUpdate);
                }

            }
        }

        if(tradeOffline.getShopId()!=null) {//如果是商户商品，则进行推送
            //获取商户账号
            Userbase userbase = shopMapper.getUserNameByShopId(tradeOffline.getShopId());
            //发送退款推送信息
            Notice notice = new Notice();
            try {
                notice.setNoticetype(0);
                notice.setSender(tradeOffline.getGroupId());
                notice.setReceiver(userbase.getUsername());
                notice.setNoticetitle("您有一笔退款申请");
                notice.setNoticetarget("ACCOUNT");
                notice.setNoticebody("您有一笔退款申请");
                notice.setGroupid(tradeOffline.getGroupId());
                notice.setNoticestatus(1);
                notice.setIsplay(0);
                notice.setType(1);
                notice.setTvalue("");
                appNoticeService.sendNoticeToUsers(notice);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
		baseOutDTO.setErrorCode(Rescode.SUCCESS, "退款成功");
		baseOutDTO.setTradeOffline(tradeOffline); 
		return baseOutDTO;
	}



    @Override
    public DeviceOfflineRecordListOutDTO queryXYJTradeList(DeviceOfflineRecordInDTO offlineRecordInDTO, Page page) throws ApplicationException {
        DeviceOfflineRecordListOutDTO deviceOfflineRecordListOutDTO = new DeviceOfflineRecordListOutDTO();

        Map<String,Object> param=new HashMap<String,Object>();
        param.put("groupId",offlineRecordInDTO.getGroupId());
        param.put("receiverId",offlineRecordInDTO.getReceiverId());
        param.put("receiverName",offlineRecordInDTO.getReceiverName());
        param.put("transactionType",offlineRecordInDTO.getTransactionType());
        param.put("payType",offlineRecordInDTO.getPayType());
        param.put("orderId",offlineRecordInDTO.getOrderId());
        param.put("agentId",offlineRecordInDTO.getAgentId());
        param.put("shopId",offlineRecordInDTO.getShopId());
        param.put("shortid",offlineRecordInDTO.getShortid());
        param.put("joinStart",offlineRecordInDTO.getJoinStart());
        param.put("joinEnd",offlineRecordInDTO.getJoinEnd());



        int sumCount = machineWasherMapper.queryXYJTradeCount(param);
        page.setTotalResult(sumCount);
        if(sumCount<=0)
            return deviceOfflineRecordListOutDTO;

        param.put("limit", page.getShowCount());
        param.put("start", page.getShowCount()*(page.getCurrentPage()-1));

        List<XYJTradeOutDTO> xyjTradeOutDTOList = machineWasherMapper.queryXYJTradeList(param);
        deviceOfflineRecordListOutDTO.setXyjTradeOutDTOList(xyjTradeOutDTOList);
        return deviceOfflineRecordListOutDTO;
    }



}
